<?php
//
// 原生PHP模板引擎
//

class PhpView
{
	static $debug = 0;
	static function initialize() { }
	
	static function display($_tpl_file)
	{
		extract(View::$vars, EXTR_OVERWRITE);	//变量的作用域只当前文件

		//set_include_path(get_include_path() .PATH_SEPARATOR. my_path('%/'));
		chdir(my_path('%/'));

		error_reporting(E_ALL ^ E_NOTICE);
		Core::trackingErrors(false);
		include self::freshStuff($_tpl_file);
		Core::trackingErrors(true);
		error_reporting(E_ALL);
	}

	/**
	  keep tpl cache purely
	  */
	static function freshStuff($_tpl_file){
		$cf = self::pathCache($_tpl_file);
		if(self::$debug || !file_exists($cf) || filemtime($_tpl_file)>filemtime($cf)){
			file_put_contents($cf, self::tplRevert($_tpl_file));
		}
		return $cf;
	}
	
	/**
	  清除页面级缓存？
	  */
	static function clearCache($theme=null)
	{
		$dp	=	opendir(View::$cacheDir);
		if(!$dp) return ;

		if($theme!==null) {
			$key	= "%%$theme";
			$len	= strlen($key);
			while($f=readdir($dp)) {
				if($key===substr($f,0,$len)) {
					unlink(View::$cacheDir.'/'.$f);
				}
			}
		}
		else {
			while($f=readdir($dp)) {
				if('%%'===substr($f,0,2)) {
					unlink(View::$cacheDir.'/'.$f);
				}
			}
		}
		closedir($dp);
	}

	/**
	  从自定义的php模板文件生成标准的php代码，会转换<??>和<{}>
	  */
	static function tplRevert($tpl_file){
		$cont = file($tpl_file);
		$len = count($cont);
		for($i=0;$i<$len;$i++){
			if(false!==strpos($cont[$i],'<?') || false!==strpos($cont[$i],'<{')){
				$cont[$i] = preg_replace_callback('~<[{\?]\s*(.*?)\s*[\?}]>~',
								array(__CLASS__,'makeup'), $cont[$i], 100 );
			}
		}
		return join('', $cont);
	}

	/** 支援smarty "|default"語法 */
	static function mkDefault($expr, $dflt){ return $expr?$expr:$dflt; } 

	/**
	  配合self::tplRevert()使用
	  */
	protected static function makeup($match){

		$orin = preg_replace_callback('~(\$\w+)((?:\.\w+)+)~',
					array(__CLASS__, 'rvrt_var'), $match[1]); //$array.key => $array['key']
		$orin = preg_replace_callback('~(\$\w+\[.*\])((?:\.\w+)+)~',
					array(__CLASS__, 'rvrt_var'), $orin); //$array['key'].key2 => $array['key']['key2']

		if('='==substr($orin, 0, 1)){ //转换"="为"echo"
			return '<?php echo '.substr($orin, 1).'; ?>';
		}
		elseif(preg_match('~^fetch_[\w]+.*$~', $orin)){ //fetch_*系列函数，不用前缀"="
			return '<?php echo '.$orin.'; ?>';
		}
		elseif(preg_match('~^php[^\w]+~', $orin)){ //php代码，不处理
			return '<?'.$orin.'; ?>';
		}
		elseif(preg_match('~^include\s*(.*?)$~', $orin, $m)){ //include語法
			return "<?php include ".__CLASS__."::freshStuff(my_path({$m[1]})); ?>";
			//考虑变量作用域，include必需显式调用，不可由函数间接输出
		}
		elseif(preg_match('~^url\s*\((.*)\)$~', $orin, $m)){ //url函数，不用前缀"="
			return "<?php echo url({$m[1]}); ?>";
		}
		elseif(preg_match('~^/[\w]+$~', $orin)){ //支援smarty块语句结束符"/"，如"/if"
			return '<?php end'.substr($orin, 1).'; ?>';
		}
		elseif('else'==$orin){ //if..else..
			return '<?php else: ?>';
		}
		elseif(preg_match('~^(if|elseif|else\s+if)\s+(.*)$~', $orin, $m)){ //支援smarty if语句
			return '<?php '.$m[1].'('.$m[2].'): ?>';
		}
		elseif('foreach'==substr($orin,0,7) && preg_match_all('~
				\s+
				(key|item|from)
				\s*=\s*
				(\$?[^\s]+)
				~x', substr($orin,7), $m)){ //支援smarty foreach语句
			$var = $key = $val = '';
			foreach($m[1] as $k=>$v){
				if($v=='item'){
					$val = '$'.$m[2][$k];
				}
				elseif($v=='key'){
					$key = '$'.$m[2][$k].' => ';
				}
				elseif($v=='from'){
					$var = $m[2][$k].' as '; 
				}
			}
			return "<?php foreach({$var}{$key}{$val}): ?>";
		}
		elseif(preg_match('~^(.*)\|default\s*:(.*)$~', $orin, $m)){ //支援smarty "|default"語法
			return '<?php echo '.__CLASS__."::mkDefault({$m[1]},{$m[2]}); ?>";
		}
		elseif('$'==substr($orin, 0, 1) && preg_match('~^
				\$\w+
				(?:
					\s*
					\[
						.*?
					\]
				)*
				$~x', $orin, $m)){ //输出合法变量
			return '<?php echo '.$m[0].'; ?>';
		}

		return '<?php '.$orin.'; ?>'; //只转换short_tag
	}

	/**
	  变量替换，配合self::makeup使用
	  */
	protected static function rvrt_var($match){
		return $match[1].join('', array_map(
								array(__CLASS__,'rvrt_var2'),
								explode('.', substr($match[2],1))
							));
	}
	protected static function rvrt_var2($v){
		return "['{$v}']";
	}

	/**
	  生成模板文件缓存路径
	  */
	protected static function pathCache($tpl_file){
		return View::$cacheDir.'/%%'.View::theme().
				str_replace('/','%', substr($tpl_file, strlen(my_path('%/'))-1));
		//return View::$cacheDir.'/%%'.View::theme().str_replace('/','%',$tpl_file);
	}
	
}

?>
